From: Jan Beulich <jbeulich@suse.com>
Subject: evtchn: relax port_is_valid()

To avoid ports potentially becoming invalid behind the back of certain
other functions (due to ->max_evtchn shrinking) because of
- a guest invoking evtchn_reset() and from a 2nd vCPU opening new
  channels in parallel (see also XSA-343),
- alloc_unbound_xen_event_channel() produced channels living above the
  2-level range (see also XSA-342),
drop the max_evtchns check from port_is_valid(). For a port for which
the function once returned "true", the returned value may not turn into
"false" later on. The function's result may only depend on bounds which
can only ever grow (which is the case for d->valid_evtchns).

This also eliminates a false sense of safety, utilized by some of the
users (see again XSA-343): Without a suitable lock held, d->max_evtchns
may change at any time, and hence deducing that certain other operations
are safe when port_is_valid() returned true is not legitimate. The
opportunities to abuse this may get widened by the change here
(depending on guest and host configuration), but will be taken care of
by the other XSA.

This is XSA-338.

Fixes: 48974e6ce52e ("evtchn: use a per-domain variable for the max number of event channels")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
Reviewed-by: Julien Grall <jgrall@amazon.com>
---
v5: New, split from larger patch.

--- a/xen/include/xen/event.h
+++ b/xen/include/xen/event.h
@@ -107,8 +107,6 @@ void notify_via_xen_event_channel(struct
 
 static inline bool_t port_is_valid(struct domain *d, unsigned int p)
 {
-    if ( p >= d->max_evtchns )
-        return 0;
     return p < read_atomic(&d->valid_evtchns);
 }
 
